Skip to content

Add context command support for chat turns - #1124

Merged
penso merged 4 commits into
moltis-org:mainfrom
gptme-thomas:pr/context-command
Jul 23, 2026
Merged

Add context command support for chat turns#1124
penso merged 4 commits into
moltis-org:mainfrom
gptme-thomas:pr/context-command

Conversation

@gptme-thomas

Copy link
Copy Markdown
Contributor

Summary

Adds an optional chat.context_command that runs before each chat turn and appends stdout to the prompt context. This lets deployments inject generated runtime context without manually pasting it into each session.

The implementation covers:

  • config schema, template, validation, and docs
  • shared context command runner with timeout/error handling
  • normal chat turn context merging
  • external-agent context snapshots
  • Codex app-server context forwarding so external-agent turns receive the generated context

Validation

  • cargo fmt --all -- --check
  • cargo test -p moltis-common context_command -- --nocapture
  • cargo test -p moltis-config context_command -- --nocapture
  • cargo test -p moltis-chat merge_context_sections -- --nocapture
  • cargo test -p moltis-gateway context_from_history_includes_project_context -- --nocapture
  • cargo test -p moltis-external-agents runtimes::codex::tests -- --nocapture

@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an optional chat.context_command configuration that executes a shell command before each chat turn and appends its stdout to the prompt context, enabling deployments to inject dynamic runtime context without manual copy-paste. The implementation is well-contained across config, a new moltis-common runner module, the chat service, the gateway's external-agent path, and the Codex app-server transport.

  • run_context_command in moltis-common handles the hard safety properties correctly: 30-second timeout with kill_on_drop, a 32 KB stdout cap (matching workspace_file_max_chars), and concurrent stderr draining to prevent pipe deadlocks — all addressed concerns raised in prior review rounds.
  • Chat turns now call resolve_turn_context which merges project-file context and command output; the sequential ordering is forced by the dependency on working_dir from resolve_project_context.
  • External-agent turns (including the Codex app-server) gain a working-dir-aware context resolution and forward command output via ContextSnapshot.project_context; the PR also adds an outer per-turn timeout to CodexAppServerSession::send_prompt and params/delta extraction to extract_message.

Confidence Score: 5/5

Safe to merge — the feature is additive, opt-in (defaults to None), and the command runner correctly handles all known failure modes (timeout, truncation, non-zero exit, pipe deadlock).

The implementation addresses the output-size cap, working-directory propagation, and warn-vs-debug log level that were flagged in prior rounds. No new correctness issues were found across the runner, chat service, gateway, or Codex transport changes.

No files require special attention.

Important Files Changed

Filename Overview
crates/common/src/context_command.rs New module implementing the core context command runner with 30s timeout, 32KB stdout cap, concurrent stderr draining to prevent pipe deadlocks, and proper kill-on-drop cleanup. Well-structured with tests covering empty input, success, failure, working-dir, and truncation cases.
crates/chat/src/service/types.rs Refactors resolve_project_context to return (Option, Option), adds resolve_turn_context that merges project file context and command output, and adds merge_context_sections. Well-tested; sequential awaiting is required since working_dir is a dependency for run_context_command.
crates/gateway/src/external_agents.rs Adds resolve_context_working_dir (worktree-aware), wires context_command output into ContextSnapshot.project_context for external-agent turns, and renames context_from_history to context_from_history_with_project_context. Project-file context was already absent from external-agent snapshots pre-PR.
crates/external-agents/src/runtimes/codex.rs Forwards context to Codex app-server via build_process_input, adds an outer per-turn timeout complementing the existing per-line timeout in consume_turn, and adds params/delta extraction to extract_message. All changes are additive and safe.
crates/config/src/schema/chat.rs Adds optional context_command: Option field with serde default None. Schema map and validation updated accordingly.
docs/src/configuration-reference.md Documents the new context_command field with accurate timeout and cap values, and correct working-directory behavior.

Sequence Diagram

sequenceDiagram
    participant User
    participant ChatService
    participant DB as ProjectService/DB
    participant Cmd as context_command
    participant LLM

    User->>ChatService: chat turn (send)
    ChatService->>DB: resolve_project_context(session, conn)
    DB-->>ChatService: (project_context_str, working_dir)
    ChatService->>Cmd: run_context_command(cmd, working_dir)
    Note over Cmd: 30s timeout, 32KB cap
    Cmd-->>ChatService: command_context (or None)
    ChatService->>ChatService: merge_context_sections()
    ChatService->>LLM: send prompt + merged context
    LLM-->>ChatService: response stream
    ChatService-->>User: streamed response

    Note over ChatService: External-agent path
    User->>ChatService: external agent turn
    ChatService->>DB: resolve_context_working_dir(session)
    DB-->>ChatService: working_dir (or None)
    ChatService->>Cmd: run_context_command(cmd, working_dir)
    Cmd-->>ChatService: context_command_output
    ChatService->>ChatService: context_from_history_with_project_context()
    ChatService->>LLM: "send_prompt(text, ContextSnapshot{project_context})"
    LLM-->>ChatService: ExternalAgentEvents
    ChatService-->>User: streamed response
Loading

Reviews (3): Last reviewed commit: "fix(context-command): cap output size an..." | Re-trigger Greptile

Comment thread crates/common/src/context_command.rs
Comment thread crates/chat/src/service/types.rs
Comment thread crates/common/src/context_command.rs
- Downgrade empty-output log from warn! to debug! — operators may
  conditionally emit context, so silence is not an error.
- Resolve project context and context command concurrently via
  tokio::join! instead of sequentially, avoiding double latency on
  every chat turn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@penso

penso commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

@greptileai review

Comment thread crates/common/src/context_command.rs Outdated
penso added 2 commits July 23, 2026 10:35
…xt-command

# Conflicts:
#	crates/config/src/template.rs
Addresses Greptile review feedback on the context command feature.

- Cap stdout at 32,000 bytes (mirrors workspace_file_max_chars) so a
  misconfigured command (e.g. `cat /var/log/app.log`) cannot exhaust
  server memory or blow past the model context window. Reads are bounded
  via a take-limited reader; the process is killed once the cap is hit.
  stderr is drained concurrently in a bounded task to avoid a pipe-buffer
  deadlock, and kill_on_drop reaps the child on timeout.
- Thread the effective working directory (session worktree, else bound
  project directory) into run_context_command at both call sites so
  operator scripts run where they expect instead of the server cwd.
- Fix a merge artifact where external_full_context still referenced the
  renamed context_from_history helper.
- Document the working-directory, timeout, and size-cap behavior in the
  config template and configuration reference.
@penso

penso commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

@greptile review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants